package happy.diandiankong.api.resource;

import com.google.common.collect.ImmutableMap;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import happy.diandiankong.api.cache.DevicePICache;
import happy.diandiankong.api.client.ApiClient;
import happy.diandiankong.api.exception.ApiServerException;
import happy.diandiankong.api.model.GpioInput;
import happy.diandiankong.api.model.Metadata;
import happy.diandiankong.api.model.ParameterValues;
import happy.diandiankong.api.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.joox.Match;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.StringReader;
import java.util.Date;

import static org.joox.JOOX.$;

/**
 * Title.
 * <p>
 * Description.
 *
 * @author Bill Lv {@literal <billcc.lv@hotmail.com>}
 * @version 1.0
 * @since 2016-10-29
 */
@Path("/api/blockly")
@Produces(MediaType.APPLICATION_JSON)
@Api("/blockly")
public class BlocklyResource {
    static final Logger LOGGER = LoggerFactory.getLogger(BlocklyResource.class);

    @POST
    @Path("/xml-parse")
    @ApiOperation("Parse XML")
    public Response parseXml(String payload) throws Exception {
        LOGGER.info("payload: {}", payload);
        if (StringUtils.isBlank(payload)) {
            return Response.ok(
                    ImmutableMap.of("code", -1, "message", "payload empty"))
                    .build();
        }
        final String newPayload = payload.replaceFirst("xmlns=\"http://www.w3.org/1999/xhtml\"", "");
        Document document = $(new StringReader(newPayload)).document();
        Match root = $(document).xpath("/xml/block");
        final Match tpCompareBlock = root.xpath("value/block[@type='logic_compare']");
        final String op = tpCompareBlock.xpath("field[@name='OP']").cdata();
        LOGGER.info("op: {}", op);
        if (tpCompareBlock.xpath("value/block[@type='temperature']").isNotEmpty()) {
            final String tp = tpCompareBlock.xpath("value/block[@type='math_number']/field[@name='NUM']").cdata();
            LOGGER.info("tp: {}", tp);
            final int tpValue = DevicePICache.getInstance().getTp();
            final int tpMisc = Integer.parseInt(tp);
            if ("LT".equals(op)) {
                if (tpValue < tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            } else if ("GT".equals(op)) {
                if (tpValue > tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            } else if ("EQ".equals(op)) {
                if (tpValue == tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            } else if ("NEQ".equals(op)) {
                if (tpValue != tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            } else if ("LTE".equals(op)) {
                if (tpValue <= tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            } else if ("GTE".equals(op)) {
                if (tpValue >= tpMisc) {
                    LOGGER.info("trigger air condition");
                    final int tpToSet = getTpToSet(root);
                    triggerGpio(true, "12");
                }
            }
        }
        return Response.ok(
                ImmutableMap.of("code", 0, "message", "success"))
                .build();
    }

    private int triggerGpio(boolean isOn, String pin) {
        final ApiClient apiClient = ApiClient.getInstance();
        final String eventDate = DateUtil.formatGPIODT(new Date());
        final ParameterValues parameterValues = new ParameterValues(isOn ? "1" : "0", pin);
        final GpioInput gpioInput = new GpioInput(eventDate, false, new Metadata(), "REST", "admin", "Assignment", "", "4deedba0-adde-4057-9163-76d588858d89", parameterValues, "Pending");
        try {
            return apiClient.postGpio(gpioInput);
        } catch (IOException e) {
            LOGGER.error("", e);
        } catch (ApiServerException e) {
            LOGGER.error("", e);
        }
        return -1;
    }

    private int getTpToSet(Match root) {
        final String tpToSet = root.xpath("statement/block[@type='condtioner']/value[@name='temperature']/block/field").cdata();
        LOGGER.info("tp to set: {}", tpToSet);
        return Integer.parseInt(tpToSet);
    }

}
